# coding=utf-8

from generator.cpp.file_type import CHeader, CPPHeader
from utils.Common import READ, SOMEIP, WRITE
from generator.cpp.types import CStruct, EnumClass, EnumItem, NameSpace
from generator.libsomeip.some_ip_type import SomeIP


def gen_someip_signal_id(someip:SomeIP):
    signal_h = CPPHeader("ecarx::transfer")
    signal_h.addInclude("cstdint")
    enumTX = EnumClass("SOMEIPTX", "int32_t")
    enumRX = EnumClass("SOMEIPRX", "int32_t")
    signalId = 0
    anno = """/** {0} */"""
    for msg in someip.msg:
        if msg.getterId != '0x0':
            signalId +=1
            enumItem=EnumItem(msg.msgName+"GetterId","{}".format(hex(SOMEIP | WRITE | signalId)),msg.desc if msg.desc == "" else anno.format(msg.desc))
            enumTX.addEmunItem(enumItem)
        if msg.setterId != '0x0':
            signalId +=1
            enumItem=EnumItem(msg.msgName+"SetterId","{}".format(hex(SOMEIP | WRITE | signalId)),msg.desc if msg.desc == "" else anno.format(msg.desc))
            enumTX.addEmunItem(enumItem)
        if msg.methodId != '0x0':
            signalId +=1
            enumItem=EnumItem(msg.msgName+"MethodId","{}".format(hex(SOMEIP | WRITE | signalId)),msg.desc if msg.desc == "" else anno.format(msg.desc))
            enumTX.addEmunItem(enumItem)
        if msg.eventId != '0x0':
            signalId +=1
            enumItem=EnumItem(msg.msgName+"EventId","{}".format(hex(SOMEIP | READ | signalId)),msg.desc if msg.desc == "" else anno.format(msg.desc))
            enumRX.addEmunItem(enumItem)

    signal_h.addMember(enumTX)
    signal_h.addMember(enumRX)

    #add enum in 'ParameterConfig'
    lastName = ""
    element = EnumClass("", "int32_t")
    for item in someip.enumList:
        if item.isEnum != True:
            continue

        if lastName == "" or lastName != item.idtName:
            if lastName != "":
                signal_h.addMember(element)
            element = EnumClass(item.idtName, "int32_t")
        enumItem=EnumItem(item.name, item.minValue, item.desc if item.desc == "" else anno.format(item.desc))
        element.addEmunItem(enumItem)
        lastName = item.idtName

    signal_h.addMember(element)
    
    
    # someip_structs.h 
    someip_struct_header = CHeader("SOME_IP_STRUCT_DEFINE_TYPE")
    someip_struct_header.include("cstdint")
    someip_struct_header.include("vector")
    someip_struct_header.include("ADCU_HmiService_types.h", True)
    names=[]

    #define serviceid,instanceid,groupid
    someip_struct_header.define("ADCU_HMI_SERVICE_ID " + someip.serviceId)
    someip_struct_header.define("ADCU_HMI_INSTANCE_ID " + someip.instanceId)
    egNameId:Dict[str, int] = {}
    for key,value in someip.eventGroupDict.items():
        egNameId[key] = value[0].eventGroupId
    for key,value in egNameId.items():
        someip_struct_header.define(key + " " + value)

    
    #define methodid,getterid,setterid,eventid
    for msg in someip.msg:
        if msg.getterId != '0x0':
            someip_struct_header.define("{}Getter {}".format(msg.msgName,str(msg.getterId)))
        if msg.setterId != '0x0':
            someip_struct_header.define("{}Setter {}".format(msg.msgName,str(msg.setterId)))
        if msg.eventId != '0x0':
            someip_struct_header.define("{}Event {}".format(msg.msgName,str(msg.eventId)))
        if msg.methodId != '0x0':
            someip_struct_header.define("{}Method {}".format(msg.msgName,str(msg.methodId)))
        
    #define struct
    ''' 使用 gos 生成的头文件结构
    for key,value in someip.idtItemDict.items():
        if value[0].idtType != "Struct":
            continue;

        # print("struct:", key)
        cstruct = CStruct("_"+key,True,1)
        for e in value:
            idtItemList2 = someip.idtItemDict.get(e.elementType,None)
            if idtItemList2 == None:
                print("cannot find elementType:", e.elementType)
                continue

            property_type = ""
            idtItem2 = idtItemList2[0]
            if idtItem2.isBaseType():
                property_type = idtItem2.idtType if "int" not in idtItem2.idtType else idtItem2.idtType+"_t"
            elif isArray(idtItem2.idtType) == True:
                # struct{ std::vector<uint32_t> a; } 
                idtItemList3 = someip.idtItemDict.get(idtItem2.elementType,None)
                if idtItemList3 == None:
                    print("cannot find elementType:", idtItem2.elementType)
                    continue
                idtItem3 = idtItemList3[0]
                if idtItem3.isBaseType():
                    property_type = idtItem3.idtType if "int" not in idtItem3.idtType else idtItem3.idtType+"_t"
                else:
                    property_type = idtItem2.elementType
                # struct{ std::vector<std::vector<uint32_t>> a; } #不支持 
            else:
                # struct { struct b }
                property_type = e.elementType

            if isArray(idtItem2.idtType) == True:
                cstruct.property("std::vector<{}> {}".format(property_type, e.elementName))
            else:
                cstruct.property("{} {}".format(property_type, e.elementName))
        
        someip_struct_header.addMember(cstruct)
        '''
        

    # namespace=NameSpace("someip")
    # signal_h.addMember(namespace)
    signal_h.toFile("./data/transfer/libsomeip/include/someip", "someip_signals.h")
    someip_struct_header.toFile("./data/transfer/libsomeip/include/someip", "someip_structs.h")


def gen_someip_signal_id_ori(someip:SomeIP):
    signal_h = CPPHeader("ecarx::transfer")
    signal_h.addInclude("cstdint")
    enumTX = EnumClass("SOMEIPTX", "int32_t")
    enumRX = EnumClass("SOMEIPRX", "int32_t")
    signalId = 0
    for msg in someip.msg:
        readWrite=WRITE if msg.isSend() else READ
        for item in msg.item:
            signalId +=1
            enumItem=EnumItem(item.msgName,"{}".format(hex(SOMEIP | readWrite | item.convertSignalType()|signalId)),"")
            if msg.isSend():
                enumTX.addEmunItem(enumItem)
            else:
                enumRX.addEmunItem(enumItem)
    
    someip_struct_header = CHeader("SOME_IP_STRUCT_DEFINE_TYPE")
    someip_struct_header.include("cstdint")
    namespace=NameSpace("someip")
    names=[]
    for msg in someip.msg:
        for item in msg.item:
            encodeType =item.encodeType
            if encodeType is not None:
                if encodeType.isEnum():
                    if encodeType.getTypeName() not in names:
                        names.append(encodeType.getTypeName())
                        enumClass= EnumClass(encodeType.getTypeName(),"int32_t")
                        for (member,_) in encodeType.members:
                            (name,value) = member.split("=")
                            enumClass.addEmunItem(EnumItem(name,value))
                        namespace.addTemplete(enumClass)
                else:
                    if encodeType.getTypeName() not in names:
                        names.append(encodeType.getTypeName())
                        cstruct=CStruct("_"+encodeType.getTypeName(),True,1)
                        for (member,_) in encodeType.members:
                            cstruct.property(member)
                        someip_struct_header.addMember(cstruct)

    signal_h.addMember(enumTX)
    signal_h.addMember(enumRX)
    signal_h.addMember(namespace)
    signal_h.toFile("./data/transfer/libsomeip/include/someip", "someip_signals.h")
    someip_struct_header.toFile("./data/transfer/libsomeip/include/someip", "someip_structs.h")
